//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.IO;
using System.Xml;
using CommunityServer.Components;

namespace CommunityServer.Reader.Components
{
	/// <summary>
	/// Summary description for Post.
	/// </summary>
	public class OpmlManager
	{

		#region Private Members


		private bool _errorsOccurred;
		private ArrayList _erroredSites;


		#endregion

		#region Constructor(s)


		public OpmlManager()
		{
			_erroredSites = new ArrayList();
		}


		#endregion

		#region Public Properties


		public bool ErrorsOccurred
		{
			get { return _errorsOccurred; }
			set { _errorsOccurred = value; }
		}

		public ArrayList ErroredSites
		{
			get { return _erroredSites; }
			set { _erroredSites = value; }
		}


		#endregion

		#region Public Methods


		public void ImportOpml(XmlDocument opmlDoc)
		{
			XmlNodeList outlines = opmlDoc.SelectNodes("/opml/body/outline");
	
			if (outlines.Count > 0)
			{
				try
				{
					RecurseOutlines(outlines, 0);	
				}
				catch (Exception)
				{
					this.ErrorsOccurred = true;
				}
				
			}
			else
			{
				throw new ApplicationException("Invalid OPML file format, or file has no feeds defined.");
			}
			
		}


		public string ExportOpml()
		{
			CSContext cntx = CSContext.Current;
			int userId				= cntx.User.UserID;
			MemoryStream stream		= new MemoryStream();
			XmlTextWriter xmlWriter = new XmlTextWriter(stream, null);
			string xmlOutput = string.Empty;
			string previousOutline = string.Empty;


			xmlWriter.WriteStartDocument(true);

			xmlWriter.WriteStartElement("opml");
			xmlWriter.WriteAttributeString("version", "1.0");
	
			xmlWriter.WriteStartElement("head");
			xmlWriter.WriteElementString("title", "Community Server Subscriptions");
			xmlWriter.WriteElementString("dateCreated", DateTime.Now.ToString());
			xmlWriter.WriteElementString("ownerName", cntx.User.DisplayName);
			xmlWriter.WriteEndElement();

			// Start working through the outlines.
			ArrayList outlines = FeedReaderDataProvider.Instance().GetOpmlFeedsFolders(userId);

			xmlWriter.WriteStartElement("body");
			for (int i = 0; i < outlines.Count; i++)
			{
				OpmlOutline outline = (OpmlOutline) outlines[i];


				// Write out a folder.
				if (previousOutline != outline.FolderName)
				{
					if (previousOutline != string.Empty)
						xmlWriter.WriteEndElement();

					xmlWriter.WriteStartElement("outline");
					xmlWriter.WriteAttributeString("text", outline.FolderName);

					previousOutline = outline.FolderName;	
				}

				// Write out the feed element.
				xmlWriter.WriteStartElement("outline");
				xmlWriter.WriteAttributeString("text", outline.Title);
				xmlWriter.WriteAttributeString("htmlUrl", outline.Link);
				xmlWriter.WriteAttributeString("type", "rss");
				xmlWriter.WriteAttributeString("xmlUrl", outline.Url);
				xmlWriter.WriteEndElement();
			}

			// Write out last outline element.
			if (previousOutline != string.Empty)
				xmlWriter.WriteEndElement();

			// Write out body tag.
			xmlWriter.WriteEndElement();

			// Write out last opml element.
			xmlWriter.WriteEndElement();

			xmlWriter.Flush();

			stream.Seek(0, SeekOrigin.Begin);
			StreamReader streamReader	= new StreamReader(stream);
			xmlOutput					= streamReader.ReadToEnd();

			return xmlOutput;

		}


		#endregion

		#region Private Methods


		private void RecurseOutlines(XmlNodeList outlines, int parentId)
		{
			int userId = CSContext.Current.User.UserID;
			int newParentId = 0;

			foreach (XmlNode outline in outlines)
			{
				XmlElement element = outline as XmlElement;

				if (element.GetAttribute("type") == "rss" ||
					element.GetAttribute("xmlUrl") != "")
				{
					// Is it a feed?
					try
					{
						AddFeedHelper.AddFeed(parentId, element.GetAttribute("xmlUrl"));	
					}
					catch (Exception)
					{
						this.ErrorsOccurred = true;
						this.ErroredSites.Add(element.GetAttribute("xmlUrl"));
					}
					
				}
				else
				{
					try
					{
						// If not, it's a folder.
						string folderName;

						// Some sites use "title", some use "text". Support both.
						if (element.GetAttribute("title") != "")
						{
							folderName = element.GetAttribute("title");
						}
						else
						{
							folderName = element.GetAttribute("text");
						}

						newParentId = FeedReaderDataProvider.Instance().AddFolder(userId, folderName, parentId);
					}
					catch (Exception)
					{
						this.ErrorsOccurred = true;
						this.ErroredSites.Add("Folder: " + element.GetAttribute("title"));
					}
				}

				XmlNodeList subOutlines = outline.SelectNodes("outline");

				if (subOutlines.Count > 0)
				{
					RecurseOutlines(subOutlines, newParentId);
				}
			}
		}

		
		#endregion


	}

}
